const jwt = require('jsonwebtoken');

const userService = require('../service/user.service');
const authService = require('../service/auth.service');
const errorTypes = require('../constants/error-types');
const md5password = require('../utils/password-handle');
const { PUBLIC_KEY } = require('../app/config');

// 登录校验
const verifyLogin = async (ctx, next) => {

  // 1.获取用户名、密码
  const { nickname, password } = ctx.request.body;
  // 2.判断用户名、密码不为空
  if (!nickname || !password) {
    const error = new Error(errorTypes.NICKNAME_OR_PASSWORD_IS_REQUIRED);
    return ctx.app.emit('error', error, ctx)
  }
  // 3.判断用户是否存在
  const result = await userService.getUserByNickname(nickname);
  if (result.length === 0) {
    const error = new Error(errorTypes.USER_DOES_NOT_EXISTS);
    return ctx.app.emit('error', error, ctx);
  }
  // 4.判断密码是否正确
  if (md5password(password) !== result[0].password) {
    const error = new Error(errorTypes.PASSWORD_IS_INCORRENT);
    return ctx.app.emit('error', error, ctx);
  }
  ctx.user = result[0];  // 保存用户
  console.log(`用户 ${ctx.user.nickname} 登录成功`);
  // 5.进行下一步 
  await next();
}

// 验证token是否有效
const verifyAuth = async (ctx, next) => {
  // 1.获取token
  const authorization = ctx.headers.authorization;
  if (!authorization) {
    // 没有传token
    const error = new Error(errorTypes.UN_AUTHORIZED);
    return ctx.app.emit('error', error, ctx);
  }
  const token = authorization.replace("Bearer ", "");
  // 2.验证token
  try {
    const result = jwt.verify(token, PUBLIC_KEY, {
      algorithms: ['RS256']
    });
    ctx.user = result;
    await next();
  } catch (err) {
    console.log("错误/过期 的 token")
    // 错误/过期 的 token
    const error = new Error(errorTypes.UN_AUTHORIZED);
    ctx.app.emit('error', error, ctx);
  }
}

// 验证用户操作权限
const verifyPermission = async (ctx, next) => {
  // 1.获取参数
  const [resourceKey] = Object.keys(ctx.params); // 操作的字段  momentId / commentId
  const tableName = resourceKey.replace("Id", ""); // 操作的表名  moment / comment
  const resourceId = ctx.params[resourceKey]; // 操作字段的值  1 / 1
  const { id } = ctx.user; // 当前用户id
  // 2.查询是否具备权限
  try {
    const isPermission = await authService.checkResource(tableName, resourceId, id);
    if (!isPermission) {// 没有权限
      const error = new Error(errorTypes.UN_PERMISSION);
      ctx.app.emit('error', error, ctx);
    } else {
      await next();
    }
  } catch (error) {
    console.log(error);
  }
}

// 验证用户是否开放博客
const verifyPrivate = async (ctx, next) => {
  const { userId } = ctx.query;
  const result = await userService.isPrivate(userId);
  if (result) {
    ctx.body = {
      code: "401",
      message: "该用户未开放博客"
    }
  } else {
    await next();
  }
}

module.exports = {
  verifyLogin,
  verifyAuth,
  verifyPermission,
  verifyPrivate
};
